﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading;
using ServerFramework.Tools;

namespace ServerFramework.ORM
{
    public enum EEntityState
    {
        None,
        Add,
        Update,
        Delete
    }
    /// <summary>
    /// 数据基类
    /// </summary>
    public class DataEntityBase
    {
        /// <summary>
        /// 锁
        /// </summary>
        private readonly object _lockFlag = new object();
        /// <summary>
        /// 数据块id 唯一确定一项数据
        /// </summary>
        [DbData(true)]
        public long id { get; set; }

        /// <summary>
        /// 上次使用时间，用来判断过期
        /// </summary>
        public DateTime UseTime = DateTime.Now;

        /// <summary>
        /// 名次 用来排序用的
        /// </summary>
        public int Rank;

        /// <summary>
        /// 实体状态
        /// </summary>
        protected EEntityState _state = EEntityState.None;
        public EEntityState GetState()
        {
            lock (_lockFlag) { return _state; }
        }

        /// <summary>
        /// 获取数据库名
        /// </summary>
        /// <returns></returns>
        public string GetDbName()
        {
            DbDataAttribute attr = Attribute.GetCustomAttribute(this.GetType(), typeof(DbDataAttribute)) as DbDataAttribute;
            if (attr != null)
            {
                return attr.DbName;
            }
            return null;
        }

        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="action"></param>
        public void ModifyLock<T>(Action<T> action) where T : DataEntityBase
        {
     
           if (action != null)
           {
               try
               {
                   Monitor.Enter(_lockFlag);
                   if(_state == EEntityState.None)
                   {
                       _state = EEntityState.Update;
                   }
                   action(this as T);
               }
               finally
               {
                   Monitor.Exit(_lockFlag);
               }
               UseTime = DateTime.Now;
           }
        }

        /// <summary>
        /// 设置实体状态
        /// </summary>
        /// <param name="state"></param>
        public void SetState(EEntityState state)
        {
            if (state != EEntityState.Update)
            {
                lock (_lockFlag)
                {
                    _state = state;
                }
            }
            else
            {
                lock(_lockFlag)
                {
                    if(_state == EEntityState.None)
                    {
                        _state = state;
                    }
                }
            }
        }

        /// <summary>
        /// 获取redis key
        /// </summary>
        /// <returns></returns>
        public string GetRedisKey()
        {
            return this.GetType().Name + "_" + id;
        }

        public static string GetRedisKey<T>(long id)
        {
            return typeof(T).Name + "_" + id;
        }

        public static long GetKeyFromRedis(string redisKey)
        {
            int index = redisKey.IndexOf("_");
            string longKey = "0";
            if(index != -1)
            {
                longKey = redisKey.Remove(0,index + 1);
            }
            long id = 0;
            long.TryParse(longKey,out id);
            return id;
        }

        public static List<string> GetRedisKeys<T>(List<long> ids)
        {
            List<string> list = new List<string>();
            string tKey = typeof(T).Name;
            for(int i =0;i<ids.Count;++i)
            {
                list.Add(tKey + "_" + ids[i]);
            }
            return list;
        }

        public static string GetDbName<T>()
        {
            DbDataAttribute attr = Attribute.GetCustomAttribute(typeof(T), typeof(DbDataAttribute)) as DbDataAttribute;
            if (attr != null)
            {
                return attr.DbName;
            }
            return null;
        }


    }
}
